﻿using System;
using System.IO;
using MMD.VMD;
using Studio;
using UnityEngine;

namespace WzhAddon
{
	public class MMD_VmdCameraLoad : BaseMgr<MMD_VmdCameraLoad>
	{
		private CameraControl cameraCtrl;
		public bool camEnabled;
		public bool YSet = true;
		private bool success;
		private CameraData[] Cam_m;
		private int t;
		private float t_f;
		public string lastCamFile;
		public HSVMDAnimationController hsvmdanimationController;
		public Transform startTransform;
		public Transform orgTransform;
		private float nowframe;
		private const int HEADER = 50;
		private const int MOTIONCOUNT = 4;
		private const int MOTIONDATA = 111;
		private const int SKINCOUNT = 4;
		private const int SKINDATA = 23;
		private const int CAMERACOUNT = 4;
		private const int CAMERADATA = 61;
		private const int ILLUMINATIONCOUNT = 4;
		private const int ILLUMINATIONDATA = 28;
		private const int SHADOWCOUNT = 4;
		private const int SHADOWDATA = 9;
		private void Start()
		{
			this.cameraCtrl = Singleton<Studio.Studio>.Instance.cameraCtrl;
			this.camEnabled = true;
			this.startTransform = new GameObject().transform;
			this.orgTransform = new GameObject().transform;
			this.orgTransform.position = Vector3.zero;
			this.orgTransform.eulerAngles = Vector3.zero;
		}

		public void SetEnnabled(bool flag)
		{
			this.camEnabled = flag;
			if (this.hsvmdanimationController == null) return;
			if (this.camEnabled)
			{
				this.cameraCtrl.SetBase(this.startTransform);
				return;
			}
			this.cameraCtrl.SetBase(this.orgTransform);
		}
		public void RealeseBase()
		{
			this.cameraCtrl.SetBase(this.orgTransform);
		}
		public void LoadVmd(string path, HSVMDAnimationController hsvmdanimationController)
		{
			if (!this.camEnabled) return;
			if (string.IsNullOrEmpty(path)) return;
			this.lastCamFile = path;
			using (BinaryReader binaryReader = new BinaryReader(File.OpenRead(path)))
			{
				VMDFormat format = new VMDFormat(binaryReader, path, "cam");
				this.LoadVmd(format, hsvmdanimationController);
			}
		}
		public void LoadVmd(VMDFormat format, HSVMDAnimationController hsvmdanimationController)
		{
			if (this.camEnabled == false) return;
			if (format.camera_list == null) return;
			if (format.camera_list.camera_count <= 0U) return;
			this.hsvmdanimationController = hsvmdanimationController;
			this.startTransform.position = hsvmdanimationController.studioChara.charInfo.transform.position;
			this.startTransform.eulerAngles = hsvmdanimationController.studioChara.charInfo.transform.eulerAngles;
			CameraData[] array = new CameraData[format.camera_list.camera_count];
			int num = 0;
			while ((long)num < (long)((ulong)format.camera_list.camera_count))
			{
				VMDFormat.CameraData cameraData = format.camera_list.camera[num];
				array[num].frame = (int)cameraData.flame_no;
				array[num].distans = cameraData.length * 0.085f;
				array[num].Pos_x = -cameraData.location.x * 0.085f;
				array[num].Pos_y = cameraData.location.y * 0.085f * hsvmdanimationController.centerBasePos.y / 8f;
				array[num].Pos_z = -cameraData.location.z * 0.085f;
				array[num].Rot_x = cameraData.rotation.x;
				this.conversionAngle(ref array[num].Rot_x);
				array[num].Rot_x = -array[num].Rot_x;
				array[num].Rot_y = cameraData.rotation.y;
				this.conversionAngle(ref array[num].Rot_y);
				array[num].Rot_z = cameraData.rotation.z;
				this.conversionAngle(ref array[num].Rot_z);
				array[num].Rot_z = -array[num].Rot_z;
				array[num].Bezier = new int[24];
				for (int i = 0; i < 24; i++)
				{
					array[num].Bezier[i] = (int)cameraData.interpolation[i];
				}
				array[num].viewAngle = cameraData.viewing_angle;
				num++;
			}
			this.Qsort(ref array, 0, array.Length - 1);
			this.Cam_m = new CameraData[array[(int)(format.camera_list.camera_count - 1U)].frame + 1];
			this.Cam_m[0] = array[0];
			this.Cam_m[0].originalframe = true;
			int num2 = 1;
			int num3 = 0;
			while ((long)num3 < (long)((ulong)(format.camera_list.camera_count - 1U)))
			{
				int num4 = array[num3 + 1].frame - array[num3].frame;
				for (int j = 1; j < num4; j++)
				{
					this.Cam_m[num2].frame = num2;
					this.Cam_m[num2].Pos_x = array[num3].Pos_x + (array[num3 + 1].Pos_x - array[num3].Pos_x) * this.BezierCurve(new Vector2(0f, 0f), new Vector2((float)array[num3 + 1].Bezier[0], (float)array[num3 + 1].Bezier[2]), new Vector2((float)array[num3 + 1].Bezier[1], (float)array[num3 + 1].Bezier[3]), new Vector2(127f, 127f), (float)(1.0 * (double)j / (double)num4)).y / 127f;
					this.Cam_m[num2].Pos_y = array[num3].Pos_y + (array[num3 + 1].Pos_y - array[num3].Pos_y) * this.BezierCurve(new Vector2(0f, 0f), new Vector2((float)array[num3 + 1].Bezier[4], (float)array[num3 + 1].Bezier[6]), new Vector2((float)array[num3 + 1].Bezier[5], (float)array[num3 + 1].Bezier[7]), new Vector2(127f, 127f), (float)(1.0 * (double)j / (double)num4)).y / 127f;
					this.Cam_m[num2].Pos_z = array[num3].Pos_z + (array[num3 + 1].Pos_z - array[num3].Pos_z) * this.BezierCurve(new Vector2(0f, 0f), new Vector2((float)array[num3 + 1].Bezier[8], (float)array[num3 + 1].Bezier[10]), new Vector2((float)array[num3 + 1].Bezier[9], (float)array[num3 + 1].Bezier[11]), new Vector2(127f, 127f), (float)(1.0 * (double)j / (double)num4)).y / 127f;
					this.Cam_m[num2].Rot_x = array[num3].Rot_x + (array[num3 + 1].Rot_x - array[num3].Rot_x) * this.BezierCurve(new Vector2(0f, 0f), new Vector2((float)array[num3 + 1].Bezier[12], (float)array[num3 + 1].Bezier[14]), new Vector2((float)array[num3 + 1].Bezier[13], (float)array[num3 + 1].Bezier[15]), new Vector2(127f, 127f), (float)(1.0 * (double)j / (double)num4)).y / 127f;
					this.Cam_m[num2].Rot_y = array[num3].Rot_y + (array[num3 + 1].Rot_y - array[num3].Rot_y) * this.BezierCurve(new Vector2(0f, 0f), new Vector2((float)array[num3 + 1].Bezier[12], (float)array[num3 + 1].Bezier[14]), new Vector2((float)array[num3 + 1].Bezier[13], (float)array[num3 + 1].Bezier[15]), new Vector2(127f, 127f), (float)(1.0 * (double)j / (double)num4)).y / 127f;
					this.Cam_m[num2].Rot_z = array[num3].Rot_z + (array[num3 + 1].Rot_z - array[num3].Rot_z) * this.BezierCurve(new Vector2(0f, 0f), new Vector2((float)array[num3 + 1].Bezier[12], (float)array[num3 + 1].Bezier[14]), new Vector2((float)array[num3 + 1].Bezier[13], (float)array[num3 + 1].Bezier[15]), new Vector2(127f, 127f), (float)(1.0 * (double)j / (double)num4)).y / 127f;
					this.Cam_m[num2].distans = array[num3].distans + (array[num3 + 1].distans - array[num3].distans) * this.BezierCurve(new Vector2(0f, 0f), new Vector2((float)array[num3 + 1].Bezier[16], (float)array[num3 + 1].Bezier[18]), new Vector2((float)array[num3 + 1].Bezier[17], (float)array[num3 + 1].Bezier[19]), new Vector2(127f, 127f), (float)(1.0 * (double)j / (double)num4)).y / 127f;
					this.Cam_m[num2].viewAngle = array[num3].viewAngle + (array[num3 + 1].viewAngle - array[num3].viewAngle) * (float)((int)this.BezierCurve(new Vector2(0f, 0f), new Vector2((float)array[num3 + 1].Bezier[20], (float)array[num3 + 1].Bezier[22]), new Vector2((float)array[num3 + 1].Bezier[21], (float)array[num3 + 1].Bezier[23]), new Vector2(127f, 127f), (float)(1.0 * (double)j / (double)num4)).y) / 127f;
					num2++;
				}
				this.Cam_m[num2] = array[num3 + 1];
				this.Cam_m[num2++].originalframe = true;
				num3++;
			}
			this.cameraCtrl.SetBase(this.startTransform);
			this.success = true;
		}
		public void SetBaseTransform(Vector3 pos, Vector3 rot)
		{
			this.startTransform.position = pos;
			this.startTransform.eulerAngles = rot;
			this.cameraCtrl.SetBase(this.startTransform);
		}
		private void Update()
		{
			if (this.success && this.camEnabled)
			{
				if (this.t != (int)this.nowframe)
				{
					this.t = (int)this.nowframe;
					if (this.t < this.Cam_m.Length - 1)
					{
						Vector3 pos = new Vector3(Cam_m[t].Pos_x, Cam_m[t].Pos_y, Cam_m[t].Pos_z);
						float num = this.Cam_m[this.t].Rot_y;
						if (this.YSet) num = 180f - num;
						Vector3 rotate = new Vector3(Cam_m[t].Rot_x, num, Cam_m[t].Rot_z);
						Vector3 distance = new Vector3(0f, 0f, Cam_m[t].distans);
						var cameraData = new CameraControl.CameraData();
						cameraData.pos = pos;
						cameraData.rotate = rotate;
						cameraData.parse = -this.Cam_m[this.t].viewAngle;
						cameraData.distance = distance;
						this.cameraCtrl.Import(cameraData);
						this.cameraCtrl.fieldOfView = this.Cam_m[this.t].viewAngle;
					}
				}
				else if (this.t + 1 < this.Cam_m.Length - 1 && !this.Cam_m[this.t + 1].originalframe)
				{
					this.t_f = this.nowframe - (float)((int)this.nowframe);
				}
			}
			this.nowframe = this.getAnimationFrame();
		}

		private float getAnimationFrame()
		{
			float result = 0f;
			AnimationState animClip = this.hsvmdanimationController.GetAnimClip();
			if (animClip != null)
			{
				AnimationClip clip = animClip.clip;
				result = animClip.length * animClip.normalizedTime * clip.frameRate / 2f;
			}
			return result;
		}

		private float getVmdCamera(BinaryReader binaryReader)
		{
			return binaryReader.ReadSingle();
		}

		private void conversionAngle(ref float rot)
		{
			rot = (float)((double)(rot * 180f) / 3.141592653589793);
		}

		private void Qsort(ref CameraData[] data, int left, int right)
		{
			int num = left;
			int num2 = right;
			int frame = data[(left + right) / 2].frame;
			do
			{
				if (num < right)
				{
					if (data[num].frame < frame)
					{
						num++;
						continue;
					}
				}
				while (num2 > left && frame < data[num2].frame)
				{
					num2--;
				}
				if (num <= num2)
				{
					CameraData cameraData = data[num];
					data[num] = data[num2];
					data[num2] = cameraData;
					num++;
					num2--;
				}
			}
			while (num <= num2);
			if (left < num2)
			{
				this.Qsort(ref data, left, num2);
			}
			if (num < right)
			{
				this.Qsort(ref data, num, right);
			}
		}
		private float BezierCurveX(float x1, float x2, float x3, float x4, float t)
		{
			return Mathf.Pow(1f - t, 3f) * x1 + 3f * Mathf.Pow(1f - t, 2f) * t * x2 + 3f * (1f - t) * Mathf.Pow(t, 2f) * x3 + Mathf.Pow(t, 3f) * x4;
		}

		private float BezierCurveY(float y1, float y2, float y3, float y4, float t)
		{
			return Mathf.Pow(1f - t, 3f) * y1 + 3f * Mathf.Pow(1f - t, 2f) * t * y2 + 3f * (1f - t) * Mathf.Pow(t, 2f) * y3 + Mathf.Pow(t, 3f) * y4;
		}
		private Vector2 BezierCurve(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t)
		{
			return new Vector2(this.BezierCurveX(p1.x, p2.x, p3.x, p4.x, t), this.BezierCurveY(p1.y, p2.y, p3.y, p4.y, t));
		}

		
		public struct CameraData
		{
			public int frame;
			public float distans;
			public float Pos_x;
			public float Pos_y;
			public float Pos_z;
			public float Rot_x;
			public float Rot_y;
			public float Rot_z;
			public float viewAngle;
			public int[] Bezier;
			public bool originalframe;
		}
	}
}
